gusucode.com > VC Socket局域网聊天程序源码 > VC Socket局域网聊天程序源码/code/Code/Server/ChatDlg.cpp
// ChatDlg.cpp : implementation file // #include "stdafx.h" #include "Chat.h" #include "ChatDlg.h" #include"SysMsgSendDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChatDlg dialog CChatDlg::CChatDlg(CWnd* pParent /*=NULL*/) : CDialog(CChatDlg::IDD, pParent) { //{{AFX_DATA_INIT(CChatDlg) m_userdisp = _T(""); m_UserNum = 0; m_OnlineNum = 0; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CChatDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CChatDlg) DDX_Control(pDX, IDC_LIST2, m_list); // DDX_Text(pDX, IDC_EDIT_DATA, m_userdisp); DDX_Text(pDX, IDC_EDIT1, m_UserNum); DDX_Text(pDX, IDC_EDIT2, m_OnlineNum); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CChatDlg, CDialog) //{{AFX_MSG_MAP(CChatDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_RECVDATA,OnRecvData) ON_WM_LBUTTONDOWN() ON_BN_CLICKED(IDC_BUTTON_SEND, OnButtonSend) ON_WM_CTLCOLOR() ON_BN_CLICKED(IDC_BTN_START_SEV, OnBtnStartSev) ON_WM_TIMER() ON_NOTIFY(NM_RCLICK, IDC_LIST2, OnRclickList2) ON_COMMAND(IDM_SENDMSG, OnSendmsg) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChatDlg message handlers BOOL CChatDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); m_list.InsertColumn(0,_T("ID")); m_list.InsertColumn(1,_T("用户名")); m_list.InsertColumn(2,_T("密码")); m_list.InsertColumn(3,_T("IP")); m_list.InsertColumn(4,_T("状态")); m_list.SetColumnWidth(0,50); m_list.SetColumnWidth(1,50); m_list.SetColumnWidth(2,50); m_list.SetColumnWidth(3,120); m_list.SetColumnWidth(4,46); m_list.SetTextColor(RGB(0,255,0)); // TODO: Add extra initialization here InitSocket(); Param *p=new Param; p->hwnd=m_hWnd; p->socket=m_socket; Pfrienddata=new UserData[15]; SetTimer(6,30000,NULL); HANDLE handle=::CreateThread(NULL,0,RecvProc,(LPVOID)p,0,NULL); CloseHandle(handle); // ReleaseHandle(handle); CWnd *pWnd=GetDlgItem(IDC_BUTTON_SEND); pWnd->ShowWindow(SW_HIDE); return TRUE; // return TRUE unless you set the focus to a control } void CChatDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CChatDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CChatDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } BOOL CChatDlg::InitSocket() { msocket=socket(AF_INET,SOCK_STREAM,0); m_socket=socket(AF_INET,SOCK_DGRAM,0); if(m_socket==INVALID_SOCKET) { MessageBox("创建失败!"); return FALSE; } char hostname[50]; int Result; Result=gethostname(hostname,50); if(Result!=0) { MessageBox("主机查找错误!","Error!",MB_OK); return FALSE; } HOSTENT* hst=NULL; CString strTemp; struct in_addr ia; CString m_strIP; m_strIP=""; hst = gethostbyname((LPCTSTR)hostname); for(int i=0;hst->h_addr_list[i];i++){ memcpy(&ia.s_addr,hst->h_addr_list[i],sizeof(ia.s_addr)); strTemp.Format("%s\n",inet_ntoa(ia)); m_strIP+=strTemp; } CWnd*p=GetDlgItem(IDC_EDIT_IP); p->SetWindowText(m_strIP); p=GetDlgItem(IDC_EDIT_PORT); p->SetWindowText("6020"); SOCKADDR_IN SevAddr; SevAddr.sin_addr=ia;// .S_un.S_addr=inet_addr("192.168.87.100");// SevAddr.sin_family=AF_INET; SevAddr.sin_port=htons(6020); Result=bind(m_socket,(sockaddr*)&SevAddr,sizeof(SOCKADDR)); if(Result==SOCKET_ERROR) { MessageBox("套节字帮定失败!"); closesocket(m_socket); return FALSE; } // SevAddr.sin_port=htons(6020); return TRUE; } DWORD CChatDlg::RecvProc(LPVOID lpParameter) { HWND hwnd=((Param*)lpParameter)->hwnd; SOCKET socket=((Param*)lpParameter)->socket; char buf[200]; // char temp[300]; SOCKADDR_IN CliAddr; int len=sizeof(SOCKADDR_IN); int Result; while(TRUE) { //::MessageBox(NULL,"Thread is Runing!","",MB_OK); Result=recvfrom(socket,buf,100,0,(sockaddr*)&CliAddr,&len); // ::MessageBox(NULL,data.Name,0,MB_OK); if(Result==SOCKET_ERROR) { ::MessageBox(NULL,"Socket ERRoR!","",MB_OK); break; } buf[strlen(buf)+1]='/0'; ::PostMessage(hwnd,WM_RECVDATA,(WPARAM)&CliAddr,(LPARAM)buf); } ::MessageBox(NULL,"Thread Exit","",MB_OK); return 0; } void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam) { SOCKADDR_IN SevAddr=*((SOCKADDR_IN*)wParam); SevAddr.sin_family=AF_INET; SevAddr.sin_port=htons(4000); // MessageBox(inet_ntoa(SevAddr.sin_addr)); SOCKET m_socket1=socket(AF_INET,SOCK_DGRAM,0); CString str=(char*)lParam; //MessageBox(str); int i=str.Find("#",0);; UINT msgType; msgType=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); CString temp; UINT id; UINT code; BOOL IsYes; UINT port1,port2,port3; int j,Num,n=0; char buf[10]; switch(msgType) { case 1:// //MessageBox("用户登录"); i=str.Find("@",0); // MessageBox(str); id=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); code=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); port1=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); port2=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); port3=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); IsYes=FALSE; int Result; for (j=0;j<UserNum;j++) { if(Pfrienddata[j].code==code&&Pfrienddata[j].id==id) { Pfrienddata[j].IsOnline=1; Pfrienddata[j].ip=inet_ntoa(SevAddr.sin_addr); Pfrienddata[j].RecvMsgPort=port3; Num=j; SevAddr.sin_port=htons(port1); Result=connect(Pfrienddata[j].m_socket,(sockaddr*)&SevAddr,sizeof(SOCKADDR)); while(Result==SOCKET_ERROR&&n<3) { Result=connect(Pfrienddata[j].m_socket,(sockaddr*)&SevAddr,sizeof(SOCKADDR)); n++; } IsYes=TRUE; sprintf(buf,"1@%d",UserNum); ///// Sleep(2000); if(Result==SOCKET_ERROR) sprintf(buf,"2@3"); /* else MessageBox("连接成功");*/ break; } } break; case 2:// // MessageBox("用户注册"); i=str.Find("@",0); Pfrienddata[UserNum].Name=str.Left(i); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); Pfrienddata[UserNum].code=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); port1=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); port2=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); i=str.Find("#",0); port3=atoi(str.Left(i)); str=str.Right(str.GetLength()-i-1); Pfrienddata[UserNum].id=1000+UserNum; Pfrienddata[UserNum].IsOnline=1; Pfrienddata[UserNum].RecvMsgPort=port3; Pfrienddata[UserNum].ip=inet_ntoa(SevAddr.sin_addr); SevAddr.sin_port=htons(port1); Result=connect(Pfrienddata[UserNum].m_socket,(sockaddr*)&SevAddr,sizeof(SOCKADDR)); while(Result==SOCKET_ERROR&&n<3) { Result=connect(Pfrienddata[UserNum].m_socket,(sockaddr*)&SevAddr,sizeof(SOCKADDR)); n++; } IsYes=TRUE; Num=UserNum; sprintf(buf,"3@%d",1000+UserNum); if(Result==SOCKET_ERROR) sprintf(buf,"2@3"); /* MessageBox("连接失败"); else MessageBox("连接成功"); */ // Sleep(2000); UserNum++; break; } m_DataStr.Empty(); m_DataStr.Format("%d*",UserNum); for (j=0;j<(int)UserNum;j++) { temp.Format("%d@%d@%s@%d@%s@%d@#",Pfrienddata[j].code,Pfrienddata[j].id,Pfrienddata[j].Name,Pfrienddata[j].IsOnline,Pfrienddata[j].ip,Pfrienddata[j].RecvMsgPort); m_DataStr+=temp; } // MessageBox(m_DataStr); if(msgType==2) { CString FileStr; for (j=0;j<UserNum;j++) { temp.Format("%d@%d@%s%@#",Pfrienddata[j].code,Pfrienddata[j].id,Pfrienddata[j].Name); FileStr+=temp; } CFile file;//将新注册用户信息写入文件. file.Open("c://userdata.txt",CFile::modeWrite); file.Write(FileStr,FileStr.GetLength()); file.Close(); } SevAddr.sin_port=htons(port2); if(IsYes) { // MessageBox(m_DataStr); int Result=sendto(m_socket1,buf,100,0,(SOCKADDR*)&SevAddr,sizeof(SOCKADDR)); //Sleep(3000); CString str=m_DataStr; int i; /* for(i=0;i<UserNum;i++) if(Pfrienddata[i].m_socket==SOCKET_ERROR) { Pfrienddata[i].IsOnline=0; Pfrienddata[i].ip="未知IP"; }*/ // send(Pfrienddata[i].m_socket,str,1000+1,0); //MessageBox(str); int SocketResult; for(i=0;i<UserNum;i++) if(Pfrienddata[i].IsOnline==1) { SocketResult=send(Pfrienddata[i].m_socket,str,str.GetLength(),0); if(SocketResult==SOCKET_ERROR) { Pfrienddata[i].IsOnline=0; Pfrienddata[i].ip="未知IP"; } } } else { sprintf(buf,"2@3"); sendto(m_socket1,buf,100,0,(SOCKADDR*)&SevAddr,sizeof(SOCKADDR)); } } void CChatDlg::OnLButtonDown(UINT nFlags, CPoint point) { CDialog::OnLButtonDown(nFlags, point); } void CChatDlg::OnButtonSend() { CSysMsgSendDlg dlg; CString str; int i; str.Format("%d*",200); if(dlg.DoModal()==IDOK) { str+=dlg.m_msg; str+="$"; for(i=0;i<UserNum;i++) { if(Pfrienddata[i].IsOnline==1) { send(Pfrienddata[i].m_socket,str,str.GetLength(),0); } } } } HBRUSH CChatDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CreateSolidBrush(RGB(100,150,240));//CDialog::OnCtlColor(pDC, pWnd, nCtlColor); if(nCtlColor==CTLCOLOR_STATIC) { pDC->SetTextColor(RGB(255,0,0)); pDC->SetBkColor(TRANSPARENT); pDC->SetBkColor(RGB(100,150,240)); } // TODO: Change any attributes of the DC here if(nCtlColor==CTLCOLOR_EDIT) { pDC->SetTextColor(RGB(0,0,255)); pDC->SetBkColor(TRANSPARENT); pDC->SetBkColor(RGB(100,150,240)); } return hbr; } void CChatDlg::OnBtnStartSev() { //////////////////读取文件中用户信息并保存在数组中////////////////// CFile file; char *ch; if(!file.Open("c://userdata.txt",CFile::modeRead)) { if(IDYES==MessageBox("查找文件失败!是否要重新创建?","Error!",MB_ICONQUESTION|MB_YESNO)) file.Open("c://userdata.txt",CFile::modeCreate); else return; } int length=file.GetLength(); ch=new char[length]; file.Read(ch,length); file.Close(); CString str=ch; CString temp2,temp3; CString Usertemp; UserNum=0; int i,j=0; i=str.Find("#"); while(i!=-1) { temp2=str.Left(i); str=str.Right(str.GetLength()-i-1); i=temp2.Find("@"); temp3=temp2.Left(i); temp2=temp2.Right(temp2.GetLength()-i-1); Pfrienddata[j].code=atoi(temp3);//1密码 i=temp2.Find("@"); temp3=temp2.Left(i); temp2=temp2.Right(temp2.GetLength()-i-1); Pfrienddata[j].id=atoi(temp3);//2用户ID i=temp2.Find("@"); temp3=temp2.Left(i); temp2=temp2.Right(temp2.GetLength()-i-1); Pfrienddata[j].Name=temp3;//3用户姓名 Pfrienddata[j].IsOnline=0; Pfrienddata[j].ip="未知IP"; i=str.Find("#"); j++; UserNum++; } m_UserNum=UserNum; for(j=0;j<15;j++) { Pfrienddata[j].m_socket=socket(AF_INET,SOCK_STREAM,0); Pfrienddata[j].RecvMsgPort=0; } ////////////////////向ListCtrl中添加用户信息//////////////////////// CString disptemp; for(j=0;j<UserNum;j++) { disptemp.Format("%d",Pfrienddata[j].id); m_list.InsertItem(j,disptemp); disptemp.Format("%s",Pfrienddata[j].Name); m_list.SetItemText(j,1,disptemp); disptemp.Format("%d",Pfrienddata[j].code); m_list.SetItemText(j,2,disptemp); disptemp.Format("%s",Pfrienddata[j].ip); m_list.SetItemText(j,3,disptemp); if(Pfrienddata[j].IsOnline==1) disptemp="在线"; else disptemp="离线"; m_list.SetItemText(j,4,disptemp); } ////////////隐藏开启服务器按纽显示发送系统信息按纽//////////////// CWnd *pWnd=GetDlgItem(IDC_BTN_START_SEV); pWnd->ShowWindow(SW_HIDE); pWnd=GetDlgItem(IDC_BUTTON_SEND); pWnd->ShowWindow(SW_SHOW); ////////////////////////////////////////////////////////////////// UpdateData(FALSE); } void CChatDlg::OnTimer(UINT nIDEvent) { /////////////////////将所有用户信息格式华保存在 m_DataStr中///////////////////////// CString temp; int j; m_DataStr.Empty(); m_DataStr.Format("%d*",UserNum); for (j=0;j<UserNum;j++) { temp.Format("%d@%d@%s@%d@%s@%d@#",Pfrienddata[j].code,Pfrienddata[j].id,Pfrienddata[j].Name,Pfrienddata[j].IsOnline,Pfrienddata[j].ip,Pfrienddata[j].RecvMsgPort); m_DataStr+=temp; } int SocketResult,i; ////////////////////////向所有在线用户发送当前所有用户信息///////////////////// for(i=0;i<UserNum;i++) if(Pfrienddata[i].IsOnline==1) { SocketResult=send(Pfrienddata[i].m_socket,m_DataStr,m_DataStr.GetLength(),0); if(SocketResult==SOCKET_ERROR) { Pfrienddata[i].IsOnline=0; closesocket(Pfrienddata[i].m_socket); Pfrienddata[i].m_socket=socket(AF_INET,SOCK_STREAM,0); Pfrienddata[i].ip="未知IP"; } } CString disptemp; m_OnlineNum=0; ////////////////////////////更新ListCtrl中的用户信息/////////////////// for(j=0;j<UserNum;j++) m_list.DeleteItem(0); for(j=0;j<UserNum;j++) { disptemp.Format("%d",Pfrienddata[j].id); m_list.InsertItem(j,disptemp); disptemp.Format("%s",Pfrienddata[j].Name); m_list.SetItemText(j,1,disptemp); disptemp.Format("%d",Pfrienddata[j].code); m_list.SetItemText(j,2,disptemp); if(Pfrienddata[j].IsOnline==1) { disptemp.Format("%s:%d",Pfrienddata[j].ip,Pfrienddata[j].RecvMsgPort); m_list.SetItemText(j,3,disptemp); disptemp="在线"; m_OnlineNum++; m_list.SetItemText(j,4,disptemp); } else { disptemp.Format("%s:%d",Pfrienddata[j].ip,Pfrienddata[j].RecvMsgPort); m_list.SetItemText(j,3,disptemp); disptemp="离线"; m_list.SetItemText(j,4,disptemp); } } ///////////////////////////////////////////////////////// m_UserNum=UserNum; UpdateData(FALSE); CDialog::OnTimer(nIDEvent); } void CChatDlg::OnRclickList2(NMHDR* pNMHDR, LRESULT* pResult) { CMenu menu; CPoint Point; menu.LoadMenu(IDR_MENU1); CMenu* pPopup = menu.GetSubMenu(0); GetCursorPos( &Point ); SetForegroundWindow(); pPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, Point.x, Point.y, this); *pResult = 0; } void CChatDlg::OnSendmsg() { }